I am trying to find a way to compare the contents of one Text attribute to another if they contain text and embedded OLE objects and they were copied using the richTextWithOle function.
For example:
//copy from one text attribute to another
o."Proposed Text" = richTextWithOle(o."Object Text")
//try to compare them
string text1 = richTextWithOle(o."Object Text")
string text2 = richTextWithOle(o."Proposed Text")
if (text1 == text2) {
print "Matches"
}
The above code finds a match for non-OLE text fields but does not find a match if the attributes had OLE objects in it (Embedded Word, Excel etc).
cpai - Tue Mar 23 11:48:15 EDT 2010 |
|
Re: Comparing Text Attributes with Text and Embedded OLE Mathias Mamsch - Tue Mar 23 17:28:22 EDT 2010
Active OLE objects, i.e. Excel, Word objects contain metadata like the creation date of the object or a unique ID of the object. If you "copy" an embedded Excel Sheet you only copy the data, but Excel will change the metadata in the copied object. This is why the objects rtf data is not identical. This is a huge problem for comparing baselines and module versions, since all objects with OLE object will appear to be changed.
There are ways to get around this problem. A solution that worked very well for me is as follows. To compare two object attributes with OLE objects I will:
1. compare the text contents without OLE. Mesage: diff between the text values
2. Count the OLE objects both object attributes. If there is a different count, you cannot do an OLE comparison, since you cannot map the OLE objects to each other. Message: "OLE object was added/deleted"
3. Compare the picture part of the OLE object (see rtf specification)
3.1 If picture is identical, compare the data length of the objects. If identical too, compare the size of the ole Object. If different, then Message: "Object was scaled". If the data length is different: Message: "Warning Invisible change to the OLE object."
3.2 if picture is different, Message: "OLE Object changed"
This is quite a complex comparison and when implementing you need to take very good care of not creating memory leaks, when parsing the richtext of 10MB OLE objects.
Regards, Mathias
|
|
Re: Comparing Text Attributes with Text and Embedded OLE cpai - Wed Mar 24 16:50:19 EDT 2010 Mathias Mamsch - Tue Mar 23 17:28:22 EDT 2010
Active OLE objects, i.e. Excel, Word objects contain metadata like the creation date of the object or a unique ID of the object. If you "copy" an embedded Excel Sheet you only copy the data, but Excel will change the metadata in the copied object. This is why the objects rtf data is not identical. This is a huge problem for comparing baselines and module versions, since all objects with OLE object will appear to be changed.
There are ways to get around this problem. A solution that worked very well for me is as follows. To compare two object attributes with OLE objects I will:
1. compare the text contents without OLE. Mesage: diff between the text values
2. Count the OLE objects both object attributes. If there is a different count, you cannot do an OLE comparison, since you cannot map the OLE objects to each other. Message: "OLE object was added/deleted"
3. Compare the picture part of the OLE object (see rtf specification)
3.1 If picture is identical, compare the data length of the objects. If identical too, compare the size of the ole Object. If different, then Message: "Object was scaled". If the data length is different: Message: "Warning Invisible change to the OLE object."
3.2 if picture is different, Message: "OLE Object changed"
This is quite a complex comparison and when implementing you need to take very good care of not creating memory leaks, when parsing the richtext of 10MB OLE objects.
Regards, Mathias
Thanks for the insight Mathias. You are right that the comparison is complex. Do you have any code examples for implementing the comparison?
I am implementing a change proposal system which compares the original attribute with the proposed attribute which was copied using richTextWithOle the function. I compare the two prior to applying changes and roll-back proposals with no changes. The problem occurs with OLE objects. My solution for now is to always apply changes to text attributes with OLE since a comparison cannot be performed.
|
|
Re: Comparing Text Attributes with Text and Embedded OLE Mathias Mamsch - Thu Mar 25 05:32:52 EDT 2010 cpai - Wed Mar 24 16:50:19 EDT 2010
Thanks for the insight Mathias. You are right that the comparison is complex. Do you have any code examples for implementing the comparison?
I am implementing a change proposal system which compares the original attribute with the proposed attribute which was copied using richTextWithOle the function. I compare the two prior to applying changes and roll-back proposals with no changes. The problem occurs with OLE objects. My solution for now is to always apply changes to text attributes with OLE since a comparison cannot be performed.
In this case you can maybe doit a simpler way. If you do not store the attribute value in the other attribute, but read it out, then change it (e.g. replace all '\' by '\\' or encrypt it so that it is no valid rtf anymore) and the OLE object won't change if you write it back. Later you can encrypt the current object text compare it to the value you stored. This way the comparison will detect changes. If you want to roll back then you can decrypt the value and store it in the object text. Note that while you do this the data will change, so you need to also store the new object text value again to the attribute.
Maybe the below code example will help. It will store the object text value in the "test proc" attribute, encoding it (using the toBase64__ perm which is VERY slow, so you might want to use a different strategy, like just replacing the RTF or something). For the comparison it will encode the object text value again, compare it to the stored value and determine a change. If there was a change it will roll back the change by decrypting the stored value, reading it out again and storing it (since when you write it back the OLE object will change again).
Note that you will also need to use Buffers instead of strings for optimal performance, but I hope you get the idea.
Regards, Mathias
Object o = current
string s
string v
// read the value
s = richTextWithOle o."Object Text"
// lets change the ole value so that Excel won't change it
toBase64_(s, v)
// compare the attributes
s = o."test proc"
if (s == "") {
o."test proc" = v
ack "Stored Value"
} else {
if (v == s) {
ack "No change ..."
} else {
ack "Changed ... Rolling back"
fromBase64_(s, v)
o."Object Text" = richText v
// note that when we write this back IDs and stuff will change so store the value
s = richTextWithOle o."Object Text"
toBase64_ (s, v)
o."test proc" = v
}
}
|
|
Re: Comparing Text Attributes with Text and Embedded OLE H.Martin-Deidier - Mon Jun 14 09:39:43 EDT 2010 Mathias Mamsch - Thu Mar 25 05:32:52 EDT 2010
In this case you can maybe doit a simpler way. If you do not store the attribute value in the other attribute, but read it out, then change it (e.g. replace all '\' by '\\' or encrypt it so that it is no valid rtf anymore) and the OLE object won't change if you write it back. Later you can encrypt the current object text compare it to the value you stored. This way the comparison will detect changes. If you want to roll back then you can decrypt the value and store it in the object text. Note that while you do this the data will change, so you need to also store the new object text value again to the attribute.
Maybe the below code example will help. It will store the object text value in the "test proc" attribute, encoding it (using the toBase64__ perm which is VERY slow, so you might want to use a different strategy, like just replacing the RTF or something). For the comparison it will encode the object text value again, compare it to the stored value and determine a change. If there was a change it will roll back the change by decrypting the stored value, reading it out again and storing it (since when you write it back the OLE object will change again).
Note that you will also need to use Buffers instead of strings for optimal performance, but I hope you get the idea.
Regards, Mathias
Object o = current
string s
string v
// read the value
s = richTextWithOle o."Object Text"
// lets change the ole value so that Excel won't change it
toBase64_(s, v)
// compare the attributes
s = o."test proc"
if (s == "") {
o."test proc" = v
ack "Stored Value"
} else {
if (v == s) {
ack "No change ..."
} else {
ack "Changed ... Rolling back"
fromBase64_(s, v)
o."Object Text" = richText v
// note that when we write this back IDs and stuff will change so store the value
s = richTextWithOle o."Object Text"
toBase64_ (s, v)
o."test proc" = v
}
}
I was not involved on the original discussion but thanks to you, I resolve my problem.
My original objective was to fully export a module content into a XML file. I even export OLE objects. During initial developements I found that OLE obejcts changed at each exportation. Now I've made the quick correction that you propose (in fact I convert OLE objects with base64_ function) and everything goes right.
However, this is not completlty clear : why OLE objects change when you read them ? Can you please clarify that point.
|
|
Re: Comparing Text Attributes with Text and Embedded OLE Mathias Mamsch - Mon Jun 14 11:03:49 EDT 2010 H.Martin-Deidier - Mon Jun 14 09:39:43 EDT 2010
I was not involved on the original discussion but thanks to you, I resolve my problem.
My original objective was to fully export a module content into a XML file. I even export OLE objects. During initial developements I found that OLE obejcts changed at each exportation. Now I've made the quick correction that you propose (in fact I convert OLE objects with base64_ function) and everything goes right.
However, this is not completlty clear : why OLE objects change when you read them ? Can you please clarify that point.
Thats not true: OLE objects will (naturally) not change when you read them, but when you copy them or write them. Imagine your OLE object contains a "Created On" Value somehow encrypted in the binary data. When you read the OLE object you will read the "Created On" Value of the object. As soon as you write the data you read from the OLE object to a new OLE object (e.g. if you baseline a module and the whole module is copied, or if you copy the object, ...) then a new OLE object will be created and it will be given a new "Created On" Value. Therefore the data of the object changes, although you did not do any changes yourself (and there is a possible flaw in the OLE implementation of the DOORS client). At least I suspect something like this happens (the "Created On" value is just an example, there is probably a unique ID contained or something).
When you write an attribute with OLE data in it and you have the OLE server application installed, the DOORS client will (at least that is my guess) open the OLE server application, which will change some data ("Unique ID" or "Created On") in the OLE object. When you compare the copied data with the original you will get changes, even though you did none.
I never tested if this will only happen, when you have the server application installed. Might be interesting to know. Hope that clarifies a bit.
Regards, Mathias
P.S.: You don't need to use base64_ to convert the OLE objects. Just take care if you store them to an attribute you change the RTF somehow, so it's not recognized as an RTF OLE anymore.
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
|
|
Re: Comparing Text Attributes with Text and Embedded OLE a_vestlin - Tue Jun 15 03:14:19 EDT 2010 Mathias Mamsch - Mon Jun 14 11:03:49 EDT 2010
Thats not true: OLE objects will (naturally) not change when you read them, but when you copy them or write them. Imagine your OLE object contains a "Created On" Value somehow encrypted in the binary data. When you read the OLE object you will read the "Created On" Value of the object. As soon as you write the data you read from the OLE object to a new OLE object (e.g. if you baseline a module and the whole module is copied, or if you copy the object, ...) then a new OLE object will be created and it will be given a new "Created On" Value. Therefore the data of the object changes, although you did not do any changes yourself (and there is a possible flaw in the OLE implementation of the DOORS client). At least I suspect something like this happens (the "Created On" value is just an example, there is probably a unique ID contained or something).
When you write an attribute with OLE data in it and you have the OLE server application installed, the DOORS client will (at least that is my guess) open the OLE server application, which will change some data ("Unique ID" or "Created On") in the OLE object. When you compare the copied data with the original you will get changes, even though you did none.
I never tested if this will only happen, when you have the server application installed. Might be interesting to know. Hope that clarifies a bit.
Regards, Mathias
P.S.: You don't need to use base64_ to convert the OLE objects. Just take care if you store them to an attribute you change the RTF somehow, so it's not recognized as an RTF OLE anymore.
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
My experience is that the OLE may change while reading it. This is an example where I load
a baseline twice and reading the object text with OLE and than compare the two strings.
So far the only result I have got is that the two strings are different.
Module m = current
Baseline b = baseline(0,5, "") // Baseline containing an object with OLE
// Load baseline first time
Module mBase = load(m, b, false)
Object o1 = object(13, mBase) // An object containing OLE
string s1 = richTextWithOle(o1."Object Text")
close(mBase)
// Load baseline second time
mBase = load(m, b, false)
Object o2 = object(13, mBase)
string s2 = richTextWithOle(o2."Object Text")
close(mBase)
// Compare
print (s1 == s2)
|
|
Re: Comparing Text Attributes with Text and Embedded OLE Mathias Mamsch - Tue Jun 15 05:16:53 EDT 2010 a_vestlin - Tue Jun 15 03:14:19 EDT 2010
My experience is that the OLE may change while reading it. This is an example where I load
a baseline twice and reading the object text with OLE and than compare the two strings.
So far the only result I have got is that the two strings are different.
Module m = current
Baseline b = baseline(0,5, "") // Baseline containing an object with OLE
// Load baseline first time
Module mBase = load(m, b, false)
Object o1 = object(13, mBase) // An object containing OLE
string s1 = richTextWithOle(o1."Object Text")
close(mBase)
// Load baseline second time
mBase = load(m, b, false)
Object o2 = object(13, mBase)
string s2 = richTextWithOle(o2."Object Text")
close(mBase)
// Compare
print (s1 == s2)
Hmm ... You are right ... thats odd ... So the DOORS client will indeed feed the OLE data through the Windows OLE Engine before putting them to the object text of an object. The reason for the change is still the same, the OLE engine will change some information (possibly a parent handle, only 4 Bytes) on the OLE object. Even disabling the application for COM does not change that behaviour.
This would mean, that my above code should not work, when you close the module and reopen it (since in this case you cannot find out if the object really changed). In this case you have not many chances, except implementing an OLE comparison. Regards, Mathias
Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS
|
|
Re: Comparing Text Attributes with Text and Embedded OLE dacapri - Tue Jan 21 04:15:15 EST 2014 Mathias Mamsch - Tue Mar 23 17:28:22 EDT 2010
Active OLE objects, i.e. Excel, Word objects contain metadata like the creation date of the object or a unique ID of the object. If you "copy" an embedded Excel Sheet you only copy the data, but Excel will change the metadata in the copied object. This is why the objects rtf data is not identical. This is a huge problem for comparing baselines and module versions, since all objects with OLE object will appear to be changed.
There are ways to get around this problem. A solution that worked very well for me is as follows. To compare two object attributes with OLE objects I will:
1. compare the text contents without OLE. Mesage: diff between the text values
2. Count the OLE objects both object attributes. If there is a different count, you cannot do an OLE comparison, since you cannot map the OLE objects to each other. Message: "OLE object was added/deleted"
3. Compare the picture part of the OLE object (see rtf specification)
3.1 If picture is identical, compare the data length of the objects. If identical too, compare the size of the ole Object. If different, then Message: "Object was scaled". If the data length is different: Message: "Warning Invisible change to the OLE object."
3.2 if picture is different, Message: "OLE Object changed"
This is quite a complex comparison and when implementing you need to take very good care of not creating memory leaks, when parsing the richtext of 10MB OLE objects.
Regards, Mathias
Hello Mathias,
I read deeply this conversation because I'd like to improve my comparison script.
So far, I'm able to compare Objects with OLE (active or not, most of mine are pictures) but, as you said before, I'm detecting changes even if they are not.
string sObjectIn_ObjectText = richTextWithOle(ObjectIn)."Object Text"
string sObjectOut_ObjectText = richTextWithOle(ObjectOut)."Object Text"
if (sObjectIn_ObjectText != sObjectOut_ObjectText) {
}
I saw that you were mentioning to replace all '\' by '\\' or encrypt it so that it is no valid rtf anymore, what does it mean?
Beside this complex way, is there any other method I can try?
Thanks a lot in advance.
Best Regards,
Daniele
|
|